package com.lottery.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.lottery.common.contants.Constants;
import com.lottery.common.contants.ReQueryResult;
import com.lottery.common.entity.PaymentRecords;
import com.lottery.common.service.OrderInfoService;
import com.lottery.pay.Model.alipay.AliPayParam;
import com.lottery.pay.service.AliPayService;
import com.lottery.pay.service.PaymentRecordsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@Service
@Slf4j
public class AliPayServiceImpl implements AliPayService {
    private ReQueryResult result = new ReQueryResult();

    @Resource
    private PaymentRecordsService recordsService;
    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private AliPayParam payParam;
    @Override
    public ReQueryResult createPayment(PaymentRecords records) throws AlipayApiException {

        String productCode="";
        if (records.getPayType()==1) {
            productCode="QUICK_MSECURITY_PAY";
        }
        if (records.getPayType()==2) {
            productCode="FAST_INSTANT_TRADE_PAY";
        }
        if (records.getPayType()==3) {
            productCode="QUICK_WAP_WAY";
        }
//        Integer count=recordsService.insertSelective(records);
//        if (count<=0){
//            log.error(" 支付订单创建失败 ");
//            result.error(Constants.INSIDE_WRONG_DESC);
//            return result;
//        }
        String body=null;
        AlipayClient alipayClient = new DefaultAlipayClient(payParam.getServerUrl(),
                payParam.getApp_id(),payParam.getPrivateKey(),
                payParam.getFormat(),payParam.getCharset(),
                payParam.getAlipayPublicKey(),payParam.getSignType());
        //1 APP支付 2.web支付
        if (records.getPayType()==1){
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel alipayTradeAppPayModel = new AlipayTradeAppPayModel();
            try {
                alipayTradeAppPayModel.setSubject(new String(records.getBody().getBytes(),"UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            alipayTradeAppPayModel.setTotalAmount("0.01");
//            alipayTradeAppPayModel.setTotalAmount(records.getTotalFee().toString());
            alipayTradeAppPayModel.setProductCode(productCode);
            alipayTradeAppPayModel.setOutTradeNo(records.getOrderNum());
            alipayTradeAppPayModel.setTimeoutExpress("30m");
            log.info("model is {}",JSON.toJSONString(alipayTradeAppPayModel));
            request.setBizModel(alipayTradeAppPayModel);
            request.setNotifyUrl(payParam.getNotifyUrl());

            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            body=response.getBody();
            log.info(" response body is {}",body);
            if(response.isSuccess()){
                log.info("ali createPayment 调用成功");
            } else {
                log.info("ali createPayment 调用失败");
            }
        }else if (records.getPayType()==2){
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            AlipayTradePagePayModel alipayTradePagePayModel=new AlipayTradePagePayModel();
            try {
                alipayTradePagePayModel.setSubject(new String(records.getBody().getBytes(),"UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            alipayTradePagePayModel.setTotalAmount(records.getTotalFee().toString());
            alipayTradePagePayModel.setProductCode(productCode);
            alipayTradePagePayModel.setOutTradeNo(records.getOrderNum());
            alipayTradePagePayModel.setTimeoutExpress("30m");

            log.info("model is {}",JSON.toJSONString(alipayTradePagePayModel));
            request.setBizModel(alipayTradePagePayModel);
            request.setNotifyUrl(payParam.getNotifyUrl());
            request.setReturnUrl("https://www.lottery360.com/");
            AlipayTradePagePayResponse response = alipayClient.sdkExecute(request);
            body=response.getBody();
            log.info(" response body is {}",body);
            if(response.isSuccess()){
                log.info("ali createPayment 调用成功");
            } else {
                log.info("ali createPayment 调用失败");
            }
        }

       if (body==null){
           log.error(" 支付订单创建 ");
           result.setData("failure");
           result.error(Constants.INSIDE_WRONG_DESC);
           return result;
       }
        records.setStatus(Constants.TYPE_TWO);
        Integer count=recordsService.updateByPrimaryKeySelective(records);
        if (count==0){
            log.error(" 支付订单更新失败 ");
            result.setData("failure");
            result.error(Constants.INSIDE_WRONG_DESC);
            return result;
        }

        result.setData(body);
        result.success(Constants.SUCCESS_DESC);
        return result;
    }

    @Override
    public ReQueryResult queryPayment(PaymentRecords records) throws AlipayApiException {
        result = new ReQueryResult();
        AlipayClient alipayClient = new DefaultAlipayClient(payParam.getServerUrl(),
                payParam.getApp_id(),payParam.getPrivateKey(),
                payParam.getFormat(),payParam.getCharset(),
                payParam.getAlipayPublicKey(),payParam.getSignType());
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel payModel = new AlipayTradeQueryModel();
        payModel.setOutTradeNo(records.getOrderNum());
        request.setBizModel(payModel);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        String body=response.getBody();
        if(response.isSuccess()){
            log.info("ali queryPayment 调用成功");
        } else {
            log.info("ali queryPayment 调用失败");
        }
        log.info("alipay query response body is {}",body);
        NutMap map=JSON.parseObject(body,NutMap.class);
        if(map.getString("code").equals("10000")){
            result.success(Constants.SUCCESS_DESC);
        }else {
            result.error(map.getString("msg"));
        }
        return result;
    }

    @Override
    public ReQueryResult refundPayment(PaymentRecords records) {
        return null;
    }

    @Override
    public ReQueryResult queryRefundPayment(PaymentRecords records) {
        return null;
    }

    @Override
    public ReQueryResult closePayment(PaymentRecords records) {
        return null;
    }

    @Override
    public ReQueryResult resultDispose(HttpServletRequest request) throws AlipayApiException {
        result = new ReQueryResult();
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        log.info("支付宝回调参数 = {}",JSON.toJSONString(params));
        boolean signVerified = AlipaySignature.rsaCheckV1(params, payParam.getAlipayPublicKey(), payParam.getCharset(), payParam.getSignType()); //调用SDK验证签名
        if(!signVerified){
            // TODO 验签失败则记录异常日志，并在response中返回failure.
            log.info("支付宝验签失败");
            result.setData("failure");
            result.error(Constants.INSIDE_WRONG_DESC);
            return result;
        }

        // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
        PaymentRecords record=new PaymentRecords(params.get("out_trade_no"),params.get("trade_no"),null,params.get("trade_status"),params.get("trade_status"),null);
        if (params.get("trade_status").equals("TRADE_SUCCESS")||params.get("trade_status").equals("TRADE_FINISHED")){
            record.setStatus(Constants.TYPE_ZERO);
        }else {
            record.setStatus(Constants.TYPE_THREE);
        }
        Integer count=recordsService.updateByPrimaryKeySelective(record);
        if (count==0){
            log.error(" 支付订单更新失败 ");
            result.setData("failure");
            result.error(Constants.INSIDE_WRONG_DESC);
            return result;
        }
        record.setTotalFee(new BigDecimal(params.get("total_amount")).multiply(new BigDecimal(100)));

        //支付结果返回业务逻辑处理
        //record
        try {
            record.setType(Constants.TYPE_TWO);
            result=orderInfoService.synthesizeOrder(record);
            if (!result.getResultCode().equals(ReQueryResult.TYPE_ZERO_ZERO_STR)){
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("订单更新失败");
            log.info(ExceptionUtils.getFullStackTrace(e));
            result.error("订单更新失败");
            return result;
        }

        result.setData("success");
        result.success(Constants.SUCCESS_DESC);
        return result;
    }


    // 将request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }
}
